package server.proxy;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.List;
import java.util.zip.GZIPInputStream;


import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
import org.jboss.netty.handler.codec.http.HttpHeaders;
import org.jboss.netty.handler.codec.http.HttpRequest;
import org.jboss.netty.handler.codec.http.HttpResponse;
import org.jboss.netty.handler.codec.http.HttpResponseStatus;


/**
 * This class sends the HTTP request to the remote host & receive the answer to the request
 * 
 * @author Maxim
 *
 */
public class RemoteHostHandler extends SimpleChannelUpstreamHandler {
	
	private HttpRequest _request;
	private HttpResponse _response;
	
	
	public RemoteHostHandler(HttpRequest request) throws IOException{
		
		this._request = request;
	}
	
	public HttpResponse getResponse(){
		
		return this._response;
	}

    @Override
	public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {

    	e.getChannel().write(this._request);
    }	
    
    public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e) {
        // Add all open channels to the global group so that they are
        // closed on shutdown.
       
    	ProxyServer.allChannels.add(e.getChannel());
    }
	
    @Override
    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception{
    	
    	this._response = (HttpResponse)e.getMessage();
    	
    	
    	switch(Config.SERVER_RUNNING_MODE){
    		case 1:
    			break;
    		case 2://deleting cookies according to the anonymous policy
    			
        		this._response.removeHeader(HttpHeaders.Names.COOKIE);
        		this._response.removeHeader(HttpHeaders.Names.SET_COOKIE);
        		this._response.removeHeader(HttpHeaders.Names.SET_COOKIE2);
    			break;
    	}
    	
    	
    	
    	List<String> tEncodings = this._response.getHeaders(HttpHeaders.Names.CONTENT_ENCODING);
    	
    	if(this._response.getStatus().equals(HttpResponseStatus.OK) & !tEncodings.isEmpty() && tEncodings.contains(HttpHeaders.Values.GZIP)){
    		
    		
    		ChannelBuffer tIn = this._response.getContent();
    		int tCompressedLength = tIn.readableBytes();
    		GZIPInputStream tGzip = new GZIPInputStream(new ByteArrayInputStream(tIn.toByteBuffer().array(), 0,tCompressedLength ));
    		
    		ChannelBuffer tOut = ChannelBuffers.dynamicBuffer();
    		byte[] tBuf = new byte[1024];
    		
    		int tRead;
    		try{
    			while((tRead = tGzip.read(tBuf)) > 0){
    				tOut.writeBytes(tBuf, 0, tRead);
    			}
    		}catch(IOException ex){}
    		
    		tIn.clear();
    		this._response.setContent(tOut);
    		
    		tEncodings.remove(HttpHeaders.Values.GZIP);
    		
    		if(tEncodings.isEmpty())
    			this._response.removeHeader(HttpHeaders.Names.CONTENT_ENCODING);
    		
    		this._response.setHeader(HttpHeaders.Names.CONTENT_LENGTH, String.valueOf(tOut.readableBytes()));
    		
    		
    		e.getChannel().close();
    		
    	}
    }
    
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {

    	System.out.println("Unexpected exception from remote host handler: " + e.getCause());
    	this._response = ProxyServerHandler.createErrorResponse("Error while processing request");
    	e.getChannel().close();
    }
}
